import axios from "axios";
import type {
  AxiosInstance,
  InternalAxiosRequestConfig,
  AxiosResponse,
  AxiosError,
} from "axios";
import { ElLoading, ElMessage } from "element-plus";
import type { LoadingInstance } from "element-plus/lib/components/loading/src/loading";
import { CONTENT_TYPE, REQUEST_TIMEOUT, HEADERS, METHOD } from "./constants";

const service: AxiosInstance = axios.create({
  // 路径前缀
  baseURL: import.meta.env.VITE_API_BASE_PATH,
  // 请求超时时间 单位毫秒
  timeout: REQUEST_TIMEOUT,
  headers: {
    [HEADERS.CONTENT_TYPE]: CONTENT_TYPE.JSON,
  },
});
// 定义⼀个请求次数的变量，⽤来记录当前页⾯总共请求的次数
let loadingRequestCount = 0;
// 初始化loading
let loadingInstance: LoadingInstance;
// 显⽰loading的函数并且记录请求次数 ++
const showLoading = () => {
  if (loadingRequestCount === 0) {
    // loading样式
    loadingInstance = ElLoading.service({
      lock: true,
      text: "Loading",
      background: "rgba(0, 0, 0, 0.5)",
    });
  }
  loadingRequestCount++;
};
// 隐藏loading的函数，并且记录请求次数 --
const hideLoading = () => {
  setTimeout(() => {
    if (loadingRequestCount <= 0) return;
    loadingRequestCount--;
    if (loadingRequestCount === 0) {
      loadingInstance.close();
    }
  }, 200);
};

// 前置拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    config.customParams = {
      // 默认显示加载动画
      showLoading: true,
      ...config.customParams,
    };
    if (config.customParams.showLoading) {
      showLoading();
    }
    formatParams(config);
    return config;
  },
  (error: AxiosError) => {
    return Promise.reject(error);
  }
);
// 后置拦截器
service.interceptors.response.use(
  (res: AxiosResponse) => {
    res.config.customParams?.showLoading && hideLoading();
    return res.data;
  },
  (error: AxiosError) => {
    ElMessage.error(error.message);
    return Promise.reject(error);
  }
);
/**
 * @description: 请求参数格式化
 * @param {InternalAxiosRequestConfig} config
 */
function formatParams(config: InternalAxiosRequestConfig) {
  if (
    config.method == METHOD.POST &&
    config.headers[HEADERS.CONTENT_TYPE] == CONTENT_TYPE.FORM_DATA
  ) {
    const formData = new FormData();
    Object.keys(config.data).forEach((key) => {
      formData.append(key, config.data[key]);
    });
    config.data = formData;
  }
  if (config.method == METHOD.GET && config.params) {
    let url = config.url as string;
    url += "?";
    const keys = Object.keys(config.params);
    for (const key of keys) {
      if (config.params[key] !== void 0 && config.params[key] !== null) {
        url += `${key}=${encodeURIComponent(config.params[key])}&`;
      }
    }
    url = url.substring(0, url.length - 1);
    config.params = {};
    config.url = url;
  }
}

export function request<T>(config: AxiosConfig): Promise<IResponse<T>> {
  return service(config);
}

export default {
  request,
};
